package log

import (
	"fmt"
	"github.com/natefinch/lumberjack"
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	"os"
	"path"
	"time"
)

// / 按天获取文件名称
func getLogFileName(level string) string {
	// 获取当前日期，格式为 "app-YYYY-MM-DD.log"
	currentDate := time.Now().Format("2006-01-02")
	return fmt.Sprintf("logs/%s/app-%s-%s.log", currentDate, level, currentDate)
}

// / 按照用户ID 获取用户名称
func getLogFileNameId(id string) string {
	// 获取当前日期，格式为 "app-YYYY-MM-DD.log"
	currentDate := time.Now().Format("2006-01-02")
	dir := fmt.Sprintf("logs/%s/users/", currentDate)
	// 确保目录存在
	err := os.MkdirAll(dir, os.ModePerm)
	if err != nil {
		fmt.Println("Failed to create directory:", err)
	}
	filename := fmt.Sprintf("app-user_%s.log", id)
	return path.Join(dir, filename)
}

func logUserFile(id string) zerolog.Logger {
	//return zerolog.New(zerolog.MultiLevelWriter(
	//	zerolog.ConsoleWriter{Out: os.Stdout}, // 输出到控制台
	//	&lumberjack.Logger{
	//		Filename:   fmt.Sprintf("./logs/app_id_%s_%s.log", id, time.Now().Format("2006-01-02")), // 按日期生成日志文件名
	//		MaxSize:    10,                                                                          // 每个文件的最大大小，单位 MB
	//		MaxBackups: 1024,                                                                        // 保留的最大日志文件个数
	//		MaxAge:     356,                                                                         // 文件保存的最大天数
	//		Compress:   false,                                                                       // 是否压缩旧的日志文件
	//	})).With().Timestamp().Logger()

	// 日志文件管理：按日期切割日志文件
	logFile := &lumberjack.Logger{
		Filename: fmt.Sprintf("./logs/%s/users/app_info_%s.log", time.Now().Format("2006-01-02"), id), // 按日期生成日志文件名
		//Filename:   getLogFileName("info"),
		MaxSize:    10,    // 每个文件的最大大小，单位 MB
		MaxBackups: 1024,  // 保留的最大日志文件个数
		MaxAge:     356,   // 文件保存的最大天数
		Compress:   false, // 是否压缩旧的日志文件
	}

	//return zerolog.New(zerolog.MultiLevelWriter(
	//	zerolog.ConsoleWriter{Out: os.Stdout}, // 输出到控制台
	//	logFile)).With().Timestamp().Logger()

	logger := log.With().Str("request_id", id).Logger()

	return logger.Output(zerolog.MultiLevelWriter(
		zerolog.ConsoleWriter{Out: os.Stdout}, // 输出到控制台
		logFile)).With().Logger()
}

func InitLogs() {
	//zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}).With().Timestamp().Logger()
	const logTimeTpl = "2006-01-02T15:04:05.000000:00"
	zerolog.TimeFieldFormat = logTimeTpl

	// 日志文件管理：按日期切割日志文件
	logInfoFile := &lumberjack.Logger{
		//Filename:   fmt.Sprintf("./logs/app_info_%s.log", time.Now().Format("2006-01-02")), // 按日期生成日志文件名
		Filename:   getLogFileName("info"),
		MaxSize:    10,    // 每个文件的最大大小，单位 MB
		MaxBackups: 1024,  // 保留的最大日志文件个数
		MaxAge:     356,   // 文件保存的最大天数
		Compress:   false, // 是否压缩旧的日志文件
	}

	logWarnFile := &lumberjack.Logger{
		//Filename:   fmt.Sprintf("./logs/app_warn_%s.log", time.Now().Format("2006-01-02")), // 按日期生成日志文件名
		Filename:   getLogFileName("warn"),
		MaxSize:    10,    // 每个文件的最大大小，单位 MB
		MaxBackups: 1024,  // 保留的最大日志文件个数
		MaxAge:     356,   // 文件保存的最大天数
		Compress:   false, // 是否压缩旧的日志文件
	}

	logErrorFile := &lumberjack.Logger{
		//Filename:   fmt.Sprintf("./logs/app_error_%s.log", time.Now().Format("2006-01-02")), // 按日期生成日志文件名
		Filename:   getLogFileName("error"),
		MaxSize:    10,    // 每个文件的最大大小，单位 MB
		MaxBackups: 1024,  // 保留的最大日志文件个数
		MaxAge:     356,   // 文件保存的最大天数
		Compress:   false, // 是否压缩旧的日志文件
	}
	consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
	// 创建一个多输出的日志器
	//multi := zerolog.MultiLevelWriter(os.Stderr, logFile)

	// 创建具体的日志记录器，按日志等级分别记录
	//infoLogger := zerolog.New(multi).Level(zerolog.InfoLevel).With().Timestamp().Logger()
	//warnLogger := zerolog.New(multi).Level(zerolog.WarnLevel).With().Timestamp().Logger()
	//errorLogger := zerolog.New(multi).Level(zerolog.ErrorLevel).With().Timestamp().Logger()

	// 日志文件管理：按日期切割日志文件

	infoLogger := zerolog.New(zerolog.MultiLevelWriter(
		consoleWriter, // 输出到控制台
		logInfoFile)).With().Timestamp().Logger()
	warnLogger := zerolog.New(zerolog.MultiLevelWriter(
		consoleWriter, // 输出到控制台
		logWarnFile)).With().Timestamp().Logger()
	errorLogger := zerolog.New(zerolog.MultiLevelWriter(
		consoleWriter, // 输出到控制台
		logErrorFile)).With().Timestamp().Logger()
	// 写入不同等级的日志
	infoLogger.Info().Msg("This is an Info message")
	warnLogger.Warn().Msg("This is a Warning message")
	errorLogger.Error().Msg("This is an Error message")

	timeStart := time.Now()
	fmt.Println("log 开始 time:", timeStart.Format("2006-01-02 15:04:05"))
	// 持续写入日志
	for i := 0; i < 10000; i++ {
		go func() {
			infoLogger.Info().Msg(fmt.Sprintf("Info log %d", i))
		}()
		go func() {
			if i%2 == 0 {
				warnLogger.Warn().Msg(fmt.Sprintf("Warning log %d", i))
			}
		}()
		go func() {
			if i%3 == 0 {
				errorLogger.Error().Msg(fmt.Sprintf("Error log %d", i))
			}
		}()

		//协程 会出错
		//id := loggerId(fmt.Sprintf("%d", i%10))
		//id.Info().Msg(fmt.Sprintf("Info log %d", i))

		go func() {
			requestContext := struct {
				ID string
			}{ID: fmt.Sprintf("%d", i)}

			//idLog := log.Output(zerolog.New(loggerId(fmt.Sprintf("Info log %d", i))).With().Logger())
			//idLog.Info().Msgf(fmt.Sprintf("------custom  id log %d", i))

			logger := log.With().Str("request_id", requestContext.ID).Logger()
			logFileName := getLogFileNameId(requestContext.ID)
			logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
			if err != nil {
				log.Fatal().Err(err).Msg("Failed to create log file.")
			}
			fileLogger := logger.Output(zerolog.MultiLevelWriter(
				consoleWriter, // 输出到控制台
				logFile)).With().Logger()
			fileLogger.Info().Msg(fmt.Sprintf("------custom  id log %d", i))

			defer func(logFile *os.File) {
				err := logFile.Close()
				if err != nil {
					log.Fatal().Err(err).Msg("Failed to close log file.")
				}
			}(logFile)
		}()

	}
	fmt.Println("log 结束 time:", timeStart.Format("2006-01-02 15:04:05"))
	fmt.Println("log 结束 耗时:", time.Now().Sub(timeStart))
}
